package cs348a.io;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.List;

import cs348a.data.SequenceData;
import cs348a.data.Site;
import cs348a.test.pilot.Pilot;

/**
 * <code>OptimizerCommander</code> sends commands to the optimizer
 * 
 * @author H.S Kim
 */
public class OptimizerCommander {
	
	private SequenceData seqData;
	
	private Command currentCommand = null;
	
	/**
	 * Deletes the next point
	 * 
	 * @param pilot
	 * @param sd
	 */
	public void deleteNextPoint(Pilot pilot, SequenceData sd){
		seqData = sd;
		
		int curveNo = pilot.getCurveNo();
		int segNo = pilot.getSegmentNo();
		
		// find index of next point
		int pointNo = curveNo*2+1;
		
		List<Site> siteList = sd.siteList;
		Site s = null;
		int nextSiteNo = 0;
		boolean passOne = false;
		for(int i = pointNo; i < siteList.size(); i++) {
			if(siteList.get(i).index != -1) {
				if(!passOne) {
					passOne = true;
				} else {
					s = siteList.get(i);
					nextSiteNo = i;
					break;
				}
			}
		}
		
		// Create command
		if(s == null) return; // TODO: handle case
		
		currentCommand = new Command(DEL_TYPE, (curveNo*2), segNo, nextSiteNo, null);
//		currentCommand = new Command(DEL_TYPE, 60, 9, 76, null); // test line
		
		sendCommand(currentCommand.toString());
	}
	
	/**
	 * Handles the delete command data
	 */
	public void handleDeleteData() {
		if(currentCommand == null) return;
		
		SequenceData sd = new SequenceData();
		sd.parseDataFile(new File("..//data//finalData//delete.sequence"));
		
		seqData.replaceSites(currentCommand.currentPtIdx, 
				currentCommand.siteIdx, sd.siteList);
		
		currentCommand = null;
	}
	
	/**
	 * Deletes the next point
	 * 
	 * @param pilot
	 * @param sd
	 */
	public void addNextPoint(Pilot pilot, SequenceData sd, float[] p){
		seqData = sd;
		
		int curveNo = pilot.getCurveNo();
		int segNo = pilot.getSegmentNo();
		
		// find index of next point
		int pointNo = curveNo*2+1;
		
		List<Site> siteList = sd.siteList;
		Site s = null;
		int nextSiteNo = 0;
		for(int i = pointNo; i < siteList.size(); i++) {
			if(siteList.get(i).index != -1) {
				s = siteList.get(i);
				nextSiteNo = i;
				break;
			}
		}
		
		// Create command
		if(s == null) return; // TODO: handle case
		
		currentCommand = new Command(ADD_TYPE, (curveNo*2), segNo, nextSiteNo, p);
		
		sendCommand(currentCommand.toString());
	}
	
	/**
	 * Handles the delete command data
	 */
	public void handleAddData() {
		if(currentCommand == null) return;
		
		SequenceData sd = new SequenceData();
		sd.parseDataFile(new File("..//data//finalData//add.sequence"));
		
		seqData.replaceSites(currentCommand.currentPtIdx, 
				currentCommand.siteIdx, sd.siteList);
		
		currentCommand = null;
	}
	
	/**
	 * Sends the command to the optimizer(Matlab)
	 * 
	 * @param command
	 */
	private void sendCommand(String command) {
		// write to command file
		File file = new File("..//data//finalData//command");
		
		Writer output = null;
		
		try {
			output = new BufferedWriter(new FileWriter(file));
			output.write(command);
			output.close();
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	static public String ADD_TYPE = new String("ADD");
	static public String DEL_TYPE = new String("DEL");
	
	static private String DELIMITER = new String(" ");
	
	/**
	 * Holds data for command
	 * 
	 * @author H.S Kim
	 */
	public class Command {
		private String type;
		
		private int currentPtIdx;
		private int currentSegIdx;
		private int siteIdx;
		
		private float[] point;
		
		/**
		 * Constructor
		 * 
		 * @param t
		 * @param pt
		 * @param seg
		 * @param site
		 * @param p
		 */
		public Command(String t, int pt, int seg, int site, float[] p) {
			type = t;
			currentPtIdx = pt;
			currentSegIdx = seg;
			siteIdx = site;
			
			if(p != null){
				point = p.clone();
			} 
		}
		
		@Override
		public String toString(){
			String command = new String(
					type + DELIMITER
					+ currentPtIdx + DELIMITER
					+ currentSegIdx + DELIMITER
					+ siteIdx + DELIMITER
					+ 0);
			if(point == null) {
				return command;
			} else {
				return command + DELIMITER
				+ point[0] + DELIMITER
				+ point[1] + DELIMITER
				+ point[2];
			}
		}
	}
}
